<?php
// +----------------------------------------------------------------------
// | sfadmin - Suifeng Administration
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2020 http://suifeng.tech All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: suifeng <1787585212@qq.com>
// +----------------------------------------------------------------------

namespace app\admin\service;

use suifeng\mvc\ModuleHelper;

class Module extends \suifeng\mvc\Service
{
    /**
     * 获取模块列表，支持缓存。
     *
     * @return array
     */
    public function get_module_list()
    {
        $list = cache('admin_module_service::get_all');
        if (!$list || APP_DEBUG) {
            $where['status'] = array('eq', 1);
            $order = 'sort asc, id asc';

            $rows = model('admin/module')->where($where)
            ->order($order)
            ->select();

            $list = array();
            foreach ($rows as $row) {
                $row['config'] = $row['config'] ? json_decode($row['config']) : [];
                $row['admin_menu'] = $row['admin_menu'] ? json_decode($row['admin_menu']) : [];
                $row['user_nav'] = $row['user_nav'] ? json_decode($row['user_nav']) : [];
                $list[$row['name']] = $row->getData();
            }

            cache('admin_module_service::get_all', $list);
        }
        return $list;
    }

    /**
     * 获取群组信息。
     *
     * @param unknown $key
     * @return unknown|NULL
     */
    public function get_module_info($key)
    {
        foreach ($this->get_module_list() as $module_info) {
            if ($module_info['id'] == $key || $module_info['name'] == $key) {
                return $module_info;
            }
        }
        return null;
    }

    /**
     * 清除缓存。
     */
    public function clear_cache()
    {
        cache('admin_module_service::get_all', null);
    }


    /**
     * 检查是否是有效的模块？
     *
     * @param unknown $name
     * @return string
     */
    public function is_valid_module($name)
    {
        return realpath(APP_PATH . $name . '/module.php');
    }

    /**
     * 根据模块名，返回对应的模块实例。
     *
     * @param unknown $name
     */
    public function get_module_instance($name)
    {
        static $instances = null;

        if (isset($instances[$name])) {
            return $instances[$name];
        }

        $file = realpath(APP_PATH . $name . '/module.php');
        if ($file) {
            require_once $file;
            $class = '\\' . \think\App::$namespace . '\\' . $name . '\\Module';
            $instances[$name] = new $class();
        } else {
            $instances[$name] = null;
        }

        return $instances[$name];
    }

    /**
     * 调用指定模块的方法。
     *
     * @param unknown $module
     * @param unknown $method
     * @param unknown $args
     */
    public function invoke_module_method($module, $method, &$args = null)
    {
        $result = null;

        if (is_string($module)) {
            $module = $this->get_module_instance($module);
        }

        if ($module === null || !method_exists($module, $method)) {
            continue;
        }

        return $module->$method($args);
    }

    /**
     * 调用所有模块对应的方法。
     *
     * @param unknown $method
     * @param unknown $args
     */
    public function invoke_all_modules($method, &$args = null)
    {
        $result = null;

        foreach (array_keys($this->get_module_list()) as $module_name) {
            $module_instance = $this->get_module_instance($module_name);
            if ($module_instance === null || !method_exists($module_instance, $method)) {
                continue;
            }

            $return = $module_instance->$method($args);

            if ($return !== null) {
                $result[] = $return;
            }
        }

        return $result;
    }


    /**
     * 注册模块所有的钩子。
     *
     * @param unknown $module
     */
    public function regiserHooks($module)
    {
        if (is_string($module)) {
            $module = self::getInstance($module);
        }

        if ($module === null) {
            return;
        }

        $ref_class = new \ReflectionAnnotatedClass($module);
        foreach ($ref_class->getMethods() as $ref_method) {
            if ($ref_method->hasAnnotation('Hook')) {
                $hook_name = $ref_method->getAnnotation('Hook')->value;
                if (empty($hook_name)) {
                    $hook_name = $ref_method->getName();
                }

                //HookHelper::register($hook_name, array($module, $ref_method->getName()));
                \think\Hook::add($hook_name, array($module, $ref_method->getName()));
            }
        }
    }
}
